/**
 * Div 图元基类
 * @class
 * @extends graphic.BaseGraphic
 */
import BaseGraphic from "../../base/BaseGraphic.js";

class BaseDiv extends BaseGraphic {
  /**
   * 水平对齐方式
   * @type {Cesium.HorizontalOrigin}
   * @private
   */
  _horizontalOrigin = Cesium.HorizontalOrigin.CENTER;

  /**
   * 垂直对齐方式
   * @type {Cesium.VerticalOrigin}
   * @private
   */
  _verticalOrigin = Cesium.VerticalOrigin.CENTER;

  /**
   * 横向偏移的px像素值
   * @type {Number}
   * @private
   */
  _offsetX = 0;

  /**
   * 纵向偏移的px像素值
   * @type {Number}
   * @private
   */
  _offsetY = 0;

  /**
   * 构造函数
   * @param {Object} options 配置参数
   * @param {Array.<Number>} [options.position=[111, 28, 0]] 经纬度[x,y,z]
   * @param {Object} options.style 样式信息
   * @param {Cesium.DistanceDisplayCondition} [options.style.distanceDisplayCondition={near: 0.1, far: 1000000}] 可视范围
   * @param {Boolean} [options.style.pointerEvents=true] DIV是否可以鼠标交互
   * @param {Boolean} [options.style.userSelect=false] 是否可以选中文本
   */
  constructor(options = {}) {
    super(options);

    // 初始化默认样式
    const defaultStyle = {
      distanceDisplayCondition: { near: 0.1, far: 1000000 },
      pointerEvents: true,
      userSelect: false,
    };

    // 合并用户样式和默认样式
    this._style = { ...defaultStyle, ...(options.style || {}) };

    // 初始化 DOM 元素
    this._domEle = this._createDomElement();

    // 初始化位置
    if (options.position) {
      this.setPosition(options.position);
    }
  }

  /**
   * 获取图元包围球
   * @readonly
   * @type {Cesium.BoundingSphere}
   */
  get boundingSphere() {
    return super.boundingSphere;
  }

  /**
   * 获取图元坐标 (笛卡尔)
   * @readonly
   * @type {Cesium.Cartesian3|null}
   */
  get cartesian3() {
    return super.cartesian3;
  }

  /**
   * 获取图元坐标串（笛卡尔）
   * @readonly
   * @type {Array.<Cesium.Cartesian3>}
   */
  get cartesian3Array() {
    return super.cartesian3Array;
  }

  /**
   * 获取几何坐标
   * @readonly
   * @type {Array}
   */
  get coordinates() {
    return super.coordinates;
  }

  /**
   * 获取或设置 Div 图元的 dom 元素
   * @type {HTMLElement}
   */
  get domEle() {
    return this._domEle;
  }

  set domEle(element) {
    if (element instanceof HTMLElement) {
      // 如果已有DOM元素，先移除旧元素
      if (this._domEle && this._domEle.parentNode) {
        this._domEle.parentNode.removeChild(this._domEle);
      }
      this._domEle = element;
      // 应用样式到新元素
      this._updateDomStyle();
    }
  }

  /**
   * 获取或设置图元是否进入编辑状态
   * @type {Boolean}
   */
  get editMode() {
    return super.editMode;
  }

  set editMode(value) {
    super.editMode = value;
  }

  /**
   * 获取几何类型
   * @readonly
   * @type {String}
   */
  get geometryType() {
    return super.geometryType;
  }

  /**
   * 获取图元所属分类
   * @readonly
   * @type {GraphicClassType}
   */
  get graphicClassType() {
    return super.graphicClassType;
  }

  /**
   * 获取图元类型
   * @readonly
   * @type {GraphicType}
   */
  get graphicType() {
    return super.graphicType;
  }

  /**
   * 获取图元 id 唯一标识
   * @readonly
   * @type {String}
   */
  get id() {
    return super.id;
  }

  /**
   * 获取或设置图元选中状态
   * @type {Boolean}
   */
  get isSelected() {
    return super.isSelected;
  }

  set isSelected(value) {
    super.isSelected = value;
    // 根据选中状态更新 DOM 样式
    if (this._domEle) {
      if (value) {
        this._domEle.classList.add("cesium-extensions-div-base-selected");
      } else {
        this._domEle.classList.remove("cesium-extensions-div-base-selected");
      }
    }
  }

  /**
   * 获取或设置图元名称
   * @type {String}
   */
  get name() {
    return super.name;
  }

  set name(value) {
    super.name = value;
  }

  /**
   * 获取图元坐标（经纬度）
   * @readonly
   * @type {Array|null}
   */
  get position() {
    return super.position;
  }

  /**
   * 获取图元坐标串（经纬度）
   * @readonly
   * @type {Array.<Array>}
   */
  get positions() {
    return super.positions;
  }

  /**
   * 获取或设置图元备注
   * @type {String}
   */
  get remarks() {
    return super.remarks;
  }

  set remarks(value) {
    super.remarks = value;
  }

  /**
   * 获取或设置图元可见性
   * @type {Boolean}
   */
  get show() {
    return super.show;
  }

  set show(value) {
    super.show = value;
    // 根据可见性更新 DOM 元素显示状态
    if (this._domEle) {
      if (value) {
        this._domEle.classList.remove("cesium-extensions-div-hidden");
      } else {
        this._domEle.classList.add("cesium-extensions-div-hidden");
      }
    }
  }

  /**
   * 获取或设置图元样式
   * @type {Object}
   */
  get style() {
    return this._style;
  }

  set style(value) {
    this._style = { ...this._style, ...value };
    this._updateDomStyle();
  }

  /**
   * 获取图元类型名称
   * @readonly
   * @type {String}
   */
  get typeName() {
    return super.typeName;
  }

  /**
   * 获取或设置用户数据
   * @type {Object}
   */
  get userData() {
    return super.userData;
  }

  set userData(value) {
    super.userData = value;
  }

  /**
   * 更新图元位置
   * @param {Cesium.Scene} scene Cesium场景对象
   */
  updatePosition(scene) {
    // 参数验证
    if (
      !scene ||
      !this._position ||
      !Array.isArray(this._position) ||
      !this._domEle
    ) {
      if (this._domEle) {
        this._domEle.style.display = "none";
      }
      return;
    }

    try {
      // 转换坐标为笛卡尔坐标
      const cartesian3 = Cesium.Cartesian3.fromDegrees(
        this._position[0],
        this._position[1],
        this._position[2] || 0
      );

      // 距离检查
      if (!this._shouldShowByDistance(scene, cartesian3)) {
        this._domEle.style.display = "none";
        return;
      }

      // 使用worldToWindowCoordinates转换坐标 - 基于参考代码实现
      const canvasHeight = scene.canvas.height;
      const windowPosition = Cesium.SceneTransforms.worldToWindowCoordinates(
        scene,
        cartesian3,
        new Cesium.Cartesian2()
      );

      // 验证转换结果
      if (
        !windowPosition ||
        isNaN(windowPosition.x) ||
        isNaN(windowPosition.y)
      ) {
        this._domEle.style.display = "none";
        return;
      }

      // 清除所有可能干扰定位的样式
      this._domEle.style.removeProperty("margin");
      this._domEle.style.removeProperty("float");
      this._domEle.style.removeProperty("transform");
      this._domEle.style.removeProperty("webkitTransform");
      this._domEle.style.removeProperty("msTransform");
      this._domEle.style.removeProperty("transformOrigin");

      // 基础定位样式已通过CSS类设置，这里只设置必要的动态样式
      // 确保boxSizing样式正确
      this._domEle.style.boxSizing = "border-box";

      // 如果指定了zIndex，则设置zIndex
      if (this._style.zIndex) {
        this._domEle.style.zIndex = this._style.zIndex;
      }

      // 计算元素宽度用于根据对齐方式计算偏移
      const elWidth = this._domEle.offsetWidth;
      const elHeight = this._domEle.offsetHeight;
      
      // 根据水平对齐方式计算水平偏移量
      let offsetX = 0;
      if (this._horizontalOrigin === Cesium.HorizontalOrigin.CENTER) {
        offsetX = -elWidth / 2; // 居中对齐
      } else if (this._horizontalOrigin === Cesium.HorizontalOrigin.RIGHT) {
        offsetX = -elWidth; // 右对齐
      } else if (this._horizontalOrigin === Cesium.HorizontalOrigin.LEFT) {
        offsetX = 0; // 左对齐
      }
      
      // 根据垂直对齐方式计算垂直偏移量
      let offsetY = 0;
      if (this._verticalOrigin === Cesium.VerticalOrigin.CENTER) {
        offsetY = -elHeight / 2; // 居中对齐
      } else if (this._verticalOrigin === Cesium.VerticalOrigin.TOP) {
        offsetY = -elHeight; // 顶部对齐
      } else if (this._verticalOrigin === Cesium.VerticalOrigin.BOTTOM) {
        offsetY = 0; // 底部对齐
      }
      // 基于参考代码的位置计算逻辑
      this._domEle.style.left = Math.round(windowPosition.x + offsetX + this._offsetX) + "px";
      // 关键修改：使用canvasHeight - windowPosition.y计算底部距离
      this._domEle.style.bottom =
        Math.round(canvasHeight - windowPosition.y + offsetY + this._offsetY) + "px";

      const occ = new Cesium.EllipsoidalOccluder(
        Cesium.Ellipsoid.WGS84,
        scene.camera.position
      );
      this._domEle.style.display = occ.isPointVisible(cartesian3)
        ? "block"
        : "none";
    } catch (e) {
      // 错误处理
      if (this._domEle) {
        this._domEle.style.display = "none";
      }
    }
  }

  /**
   * 根据距离判断是否应该显示
   * @private
   * @param {Cesium.Scene} scene Cesium场景对象
   * @param {Cesium.Cartesian3} cartesian3 笛卡尔坐标
   * @returns {Boolean} 是否应该显示
   */
  _shouldShowByDistance(scene, cartesian3) {
    if (!this._style.distanceDisplayCondition) return true;

    const distance = Cesium.Cartesian3.distance(
      scene.camera.position,
      cartesian3
    );
    const { near, far } = this._style.distanceDisplayCondition;

    return distance >= near && distance <= far;
  }

  /**
   * 销毁对象
   */
  destroy() {
    if (this.isDestroyed()) {
      return;
    }

    // 移除 DOM 元素
    if (this._domEle && this._domEle.parentNode) {
      this._domEle.parentNode.removeChild(this._domEle);
    }
    this._domEle = null;

    super.destroy();
  }

  /**
   * 下载到本地
   * @param {String} name 文件名称
   */
  downloadToLocalFile(name) {
    return super.downloadToLocalFile(name);
  }

  /**
   * 触发事件
   * @param {*} type 事件类型
   */
  fire(type) {
    return super.fire(type);
  }

  /**
   * 对象是否已经销毁
   * @returns {Boolean}
   */
  isDestroyed() {
    return super.isDestroyed();
  }

  /**
   * 注销事件
   * @param {*} type 事件类型
   */
  off(type) {
    return super.off(type);
  }

  /**
   * 注册事件
   * @param {*} type 事件类型
   * @param {*} callback 回调函数
   */
  on(type, callback) {
    return super.on(type, callback);
  }

  /**
   * 设置图元坐标
   * @param {Array} position 坐标值，[x,y,z]
   */
  setPosition(position) {
    super.setPosition(position);
    // 触发位置更新事件
    this.fire("positionChanged");
  }

  /**
   * 设置图元坐标串
   * @param {Array.<Array>} positions 坐标串，[[x,y,z],[x,y,z],...]
   */
  setPositions(positions) {
    super.setPositions(positions);
    // 触发位置更新事件
    this.fire("positionsChanged");
  }

  /**
   * 转为 GeoJson 对象
   * @returns {Object} 转换后的对象
   */
  toGeoJson() {
    return super.toGeoJson();
  }

  /**
   * 创建 DOM 元素
   * @private
   * @returns {HTMLElement}
   */
  _createDomElement() {
    const div = document.createElement("div");
    div.id = this.id;

    // 添加基础CSS类
    div.className = "cesium-extensions-div-base";

    // 根据样式设置额外的CSS类
    if (this._style.pointerEvents === false) {
      div.classList.add("cesium-extensions-div-no-pointer");
    }

    if (this._style.userSelect) {
      div.classList.add("cesium-extensions-div-selectable");
    }

    // 应用其他样式
    this._updateDomStyle(div);

    return div;
  }

  /**
   * 更新 DOM 样式
   * @private
   * @param {HTMLElement} [element=this._domEle] 要更新样式的元素
   */
  _updateDomStyle(element = this._domEle) {
    if (!element) return;

    const style = this._style || {};

    // 应用所有常见样式属性（这些是需要动态设置的，不适合通过CSS类管理）
    const styleProperties = {
      width: typeof style.width === "number" ? `${style.width}px` : style.width,
      height:
        typeof style.height === "number" ? `${style.height}px` : style.height,
      backgroundColor: style.backgroundColor,
      color: style.color,
      fontSize:
        typeof style.fontSize === "number"
          ? `${style.fontSize}px`
          : style.fontSize,
      fontWeight: style.fontWeight,
      padding: style.padding,
      margin: style.margin,
      borderRadius: style.borderRadius,
      border: style.border,
      opacity: style.opacity,
      zIndex: style.zIndex,
      textAlign: style.textAlign,
      lineHeight: style.lineHeight,
      // 直接设置pointerEvents属性，确保优先级高于CSS类
      pointerEvents: style.pointerEvents === false ? "none" : "auto",
      // 直接设置userSelect属性
      userSelect: style.userSelect ? "text" : "none",
    };

    // 应用所有有效的样式属性
    Object.entries(styleProperties).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        element.style[key] = value;
      }
    });

    // 更新交互相关的CSS类（保留以兼容旧代码，但直接样式设置有更高优先级）
    if (style.pointerEvents === false) {
      element.classList.add("cesium-extensions-div-no-pointer");
    } else {
      element.classList.remove("cesium-extensions-div-no-pointer");
    }

    if (style.userSelect) {
      element.classList.add("cesium-extensions-div-selectable");
    } else {
      element.classList.remove("cesium-extensions-div-selectable");
    }

    // 直接设置为block显示，不依赖_show属性
    element.classList.remove("cesium-extensions-div-hidden");
  }
}

export default BaseDiv;
